﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Xml;
using System.Windows.Documents;
using System.Text;
using System.Windows.Data;
using System.Windows.Controls.Primitives;
using System.Drawing.Text;
using System.Windows.Markup;
using System.Collections.Generic;

namespace SHomeWorkshop.LunarMind.Dialogs
{
    /// <summary>
    /// Interaction logic for TitleCommentEditor.xaml
    /// </summary>
    public partial class TitleCommentEditor : Window
    {
        public TitleCommentEditor(List<Title> titles, string initializeText = null)
        {
            InitializeComponent();

            this.initializeText = initializeText;

            //禁用原来的快捷菜单。
            mainRTB.ContextMenu = null;

            this.masterTitles = titles;

            InputMethod.SetIsInputMethodEnabled(mainRTB, true);

            //给边框添加变色效果，结果发现有打扰人的反面效果，于是改成只闪动两次。
            //Brush myBrush = new SolidColorBrush();

            //ColorAnimation myColorAnimation = new ColorAnimation();

            //myColorAnimation.From = Colors.Transparent;

            //myColorAnimation.To = Colors.DarkCyan;
            //myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(200));
            //myColorAnimation.AutoReverse = true;
            //myColorAnimation.RepeatBehavior = new RepeatBehavior(2);

            ////将动画应用到画刷（Brush）的“Color”属性。
            //myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);
            //outBorder.BorderBrush = myBrush;

            if (titles == null)
            {
                mainRTB.Selection.Text = "没有指定要编辑的标题！";
                mainRTB.IsEnabled = false;
                btnOk.IsEnabled = false;
                return;
            }

            if (titles.Count <= 0)
            {
                mainRTB.Selection.Text = "没有指定要编辑的标题！";
                mainRTB.IsEnabled = false;
                btnOk.IsEnabled = false;
                return;
            }

            Title mainSelTitle = null;
            foreach (Title t in titles)
            {
                if (t.IsMainSelectedTitle)
                {
                    mainSelTitle = t;
                    break;
                }
            }

            if (mainSelTitle != null)
            {
                mainRTB.Background = mainSelTitle.TitleBackground;
            }

            mainRTB.SelectAll();
            mainRTB.Focus();

            colorPickerPopup.Child = colorPicker;
            colorPicker.Closed += new EventHandler<EventArgs>(colorPicker_Closed);
            colorPicker.ColorPicked += new EventHandler<ColorPickedEventArgs>(colorPicker_ColorPicked);


            #region 列出所有可用字体。

            InstalledFontCollection clsInstalledFontCollection = new InstalledFontCollection();
            System.Drawing.FontFamily[] affInstalledFont = clsInstalledFontCollection.Families;
            foreach (System.Drawing.FontFamily f in affInstalledFont)
            {
                cbFont.Items.Add(f.Name);
            }

            // 注意：上面使用的是System.Drawing下的FontFamily类，
            // 而下面使用的是System.Window.Media下的FontFamily。
            // 好不容易才找到如何解决问题的办法。
            LanguageSpecificStringDictionary fontDics = this.FontFamily.FamilyNames;
            if (fontDics.ContainsKey(XmlLanguage.GetLanguage("zh-cn")))
            {
                string fontName = null;
                if (fontDics.TryGetValue(XmlLanguage.GetLanguage("zh-cn"), out fontName))
                {
                    Globals.SysFontFamily = fontName;
                }
            }

            //if (cbFont.Items.Contains(Globals.SysFontFamily))
            //{
            //    cbFont.SelectedItem = Globals.SysFontFamily;
            //}

            //cbFontSize.SelectedIndex = 6;//字号默认是16，索引是6。
            #endregion


            //读取并初始化文本内容。

            ReadLines();//这行有必要放在判断外面——因为需要初始化字号、字型！！！

            if (initializeText == null || initializeText.Length <= 0)
            {
                this.mainRTB.SelectAll();
            }
            else
            {
                this.mainRTB.SelectAll();
                this.mainRTB.Selection.Text = "";
                this.mainRTB.AppendText(initializeText);
            }

            //注意，此事件必须在载入初始化文本之后再挂接，否则会出现选择区初始字号不同步的问题。
            cbFontSize.SelectionChanged += new SelectionChangedEventHandler(cbFontSize_SelectionChanged);
        }

        private void ReadLines()
        {
            Title mainSelectedTitle = Globals.MainWindow.MainSelectedTitle;
            if (masterTitles.Contains(mainSelectedTitle) == false) return;

            XmlNode commentSetNode = mainSelectedTitle.XmlData.SelectSingleNode("CommentSet");
            if (commentSetNode == null)
            {
                commentSetNode = mainSelectedTitle.XmlData.AppendXml("<CommentSet xml:space=\"preserve\"/>");
            }
            else
            {
                if (commentSetNode.GetAttribute("xml:space") == null)
                {
                    commentSetNode.SetAttribute("xml:space", "preserve");
                }
            }

            if (commentSetNode == null)
            {
                MessageBox.Show("出现意外错误，找不到“<CommentSet />”节点，且尝试添加失败！无法继续编辑标题的备注文本！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            XmlNodeList nlist = commentSetNode.SelectNodes("Text");
            if (nlist == null || nlist.Count <= 0)
            {
                //最初不支持格式文本，只是用一个Attribute来存放备注文本值。
                //2011年11月20日准备支持格式化的标题备注文本。
                XmlAttribute attrComment = mainSelectedTitle.XmlData.GetAttribute("CommentText");

                if (attrComment != null)
                {
                    commentSetNode.AppendXml("<Text>" + attrComment.Value + "</Text>");
                    mainSelectedTitle.XmlData.RemoveAttributeByName("CommentText");
                }
                //else
                //{
                //    commentSetNode.AppendXml("<Text />");//这会造成意外的空行。
                //}

                nlist = commentSetNode.SelectNodes("Text");
            }

            //if (nlist == null || nlist.Count <= 0)
            //{
            //    MessageBox.Show("出现意外错误，找不到“<CommentSet />”的子节点，且尝试添加失败！无法继续编辑标题的备注文本！",
            //           Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            //    return;
            //}

            Paragraph newParagraph = new Paragraph();
            mainDoc.Blocks.Add(newParagraph);

            double defFontSize = -1;
            FontFamily defFontFamily = null;

            foreach (XmlNode node in nlist)
            {
                if (node.InnerText == null || node.InnerText.Length == 0)
                {
                    newParagraph = new Paragraph();
                    mainDoc.Blocks.Add(newParagraph);
                    continue;
                }

                Run run = new Run(node.InnerText);

                //读取出所有格式信息。
                //取文本特性

                XmlAttribute attrBackground = node.GetAttribute("Background");
                if (attrBackground != null)
                {
                    Brush background = ColorPicker.GetBrushByName(attrBackground.Value);
                    if (background != null)
                        run.Background = background;
                }
                else
                {
                    run.Background = Brushes.Transparent;
                }

                XmlAttribute attrForeground = node.GetAttribute("Foreground");
                if (attrForeground != null && attrForeground.Value != "UnKnown")
                {
                    Brush foreground = ColorPicker.GetBrushByName(attrForeground.Value);
                    if (foreground != null)
                        run.Foreground = foreground;
                    else
                    {
                        run.Foreground = Globals.MainWindow.IsLightDocumentBackground ? Brushes.Black : Brushes.White;
                    }
                }
                else
                {
                    if (run.Background == null || run.Background == Brushes.Transparent)
                    {
                        var tbg = Globals.MainWindow.MainSelectedTitle.TitleBackground as SolidColorBrush;

                        if (tbg != null && tbg != Brushes.Transparent)
                        {
                            var tbc = tbg.Color;
                            run.Foreground = Globals.IsLightColor(tbc) ? Brushes.Black : Brushes.White;
                        }
                        else
                        {
                            run.Foreground = Globals.MainWindow.IsLightDocumentBackground ? Brushes.Black : Brushes.White;
                        }
                    }
                    else
                    {
                        var rbg = run.Background as SolidColorBrush;
                        if (rbg != null)
                        {
                            run.Foreground = Globals.IsLightColor(rbg.Color) ? Brushes.Black : Brushes.White;
                        }
                        else
                        {
                            run.Foreground = Globals.MainWindow.IsLightDocumentBackground ? Brushes.Black : Brushes.White;
                        }
                    }
                }

                XmlAttribute attrFontSize = node.GetAttribute("FontSize");
                if (attrFontSize != null)
                {
                    double fs = double.Parse(attrFontSize.Value);
                    run.FontSize = fs;
                    if (defFontSize < 0 && fs != defFontSize)
                    {
                        defFontSize = fs;//取第一个为默认值。
                    }
                }

                XmlAttribute attrFontWeight = node.GetAttribute("FontWeight");
                if (attrFontWeight != null && attrFontWeight.Value == "Bold")
                {
                    run.FontWeight = FontWeights.Bold;
                }

                XmlAttribute attrFontStyle = node.GetAttribute("FontStyle");
                if (attrFontStyle != null && attrFontStyle.Value == "Italic")
                {
                    run.FontStyle = FontStyles.Italic;
                }

                XmlAttribute attrUnderLine = node.GetAttribute("UnderLine");
                if (attrUnderLine != null && attrUnderLine.Value == "True")
                {
                    run.TextDecorations.Add(TextDecorations.Underline);
                }

                XmlAttribute attrStrikeLine = node.GetAttribute("StrikeLine");
                if (attrStrikeLine != null && attrStrikeLine.Value == "True")
                {
                    run.TextDecorations.Add(TextDecorations.Strikethrough);
                }

                XmlAttribute attrFontName = node.GetAttribute("FontName");
                if (attrFontName != null)
                {
                    FontFamily fontFamily = new FontFamily(attrFontName.Value);
                    if (fontFamily != null)
                        run.FontFamily = fontFamily;

                    if (defFontFamily == null)
                    {
                        defFontFamily = fontFamily;
                    }
                }

                XmlAttribute attrBaseLineAlignment = node.GetAttribute("BaseLineAlignment");
                if (attrBaseLineAlignment != null)
                {
                    switch (attrBaseLineAlignment.Value)
                    {
                        case "Top":
                            {
                                run.BaselineAlignment = BaselineAlignment.Top;
                                run.FontSize = mainRTB.FontSize / 2;
                                break;
                            }
                        case "Bottom":
                            {
                                run.BaselineAlignment = BaselineAlignment.Bottom;
                                run.FontSize = mainRTB.FontSize / 2;
                                break;
                            }
                        default:
                            {
                                run.BaselineAlignment = BaselineAlignment.Baseline;
                                break;
                            }
                    }
                }

                newParagraph.Inlines.Add(run);
            }

            if (defFontSize > 15)//默认为15
            {
                mainRTB.FontSize = defFontSize;
            }

            if (mainRTB.FontSize >= 32)
            {
                TextOptions.SetTextFormattingMode(mainRTB, TextFormattingMode.Ideal);
            }
            else
            {
                TextOptions.SetTextFormattingMode(mainRTB, TextFormattingMode.Display);
            }

            if (defFontFamily == null)
            {
                mainRTB.FontFamily = Globals.DefFontFamily;
            }
            else
            {
                mainRTB.FontFamily = defFontFamily;
            }

            if (mainSelectedTitle.TitleBackground == null || mainSelectedTitle.TitleBackground == Brushes.Transparent)
            {
                mainRTB.Foreground = Globals.MainWindow.IsLightDocumentBackground ? Brushes.Black : Brushes.White;
            }
            else
            {
                var dbsh = mainSelectedTitle.TitleBackground as SolidColorBrush;
                if (dbsh == null)
                {
                    mainRTB.Foreground = Globals.MainWindow.IsLightDocumentBackground ? Brushes.Black : Brushes.White;
                }
                else
                {
                    mainRTB.Foreground = Globals.IsLightColor(dbsh.Color) ? Brushes.Black : Brushes.White;
                }
            }
        }

        private bool WriteLinesToAllTitleXmlData()
        {
            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置（编辑）标题备注文本内容"
            };

            foreach (Title t in masterTitles)
            {
                if (WriteLinesToOneTitleCommentXmlData(mi, t) == false) return false;
            }

            Globals.MainWindow.Do(mi);
            Globals.MainWindow.IsModified = true;
            return true;
        }

        private bool WriteLinesToOneTitleCommentXmlData(ModifingItem mi, Title title)
        {
            if (title == null || title.XmlData == null)
            {
                MessageBox.Show("发现意外错误，没有传入标题，或传入的标题没有后台数据节点！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            StringBuilder sb = new StringBuilder();

            foreach (Block block in mainDoc.Blocks)
            {
                Paragraph paragraph = block as Paragraph;
                if (paragraph == null) continue;

                #region 处理空行
                if (paragraph.Inlines.Count <= 0 ||
                            paragraph.Inlines.FirstInline == null)//否则本身就是换行。
                {
                    sb.Append("<Text />");//<Text />表示换行。
                    continue;
                }

                #endregion

                foreach (Inline inline in paragraph.Inlines)
                {
                    Run run = inline as Run;
                    if (run != null && run.Text.Length > 0)
                    {
                        sb.Append("<Text ");//不完整的tab，因为要考虑特性。

                        //取出各格式特性值。
                        sb.Append("Foreground=\"");
                        sb.Append(ColorPicker.GetBrushName(run.Foreground));
                        sb.Append("\" ");

                        sb.Append("Background=\"");
                        sb.Append(ColorPicker.GetBrushName(run.Background));
                        sb.Append("\" ");

                        if (run.FontSize != Globals.MainWindow.DefaultFontSize)
                        {
                            sb.Append("FontSize=\"");
                            sb.Append(run.FontSize);
                            sb.Append("\" ");
                        }

                        sb.Append("FontWeight=\"");
                        sb.Append(run.FontWeight.ToString());
                        sb.Append("\" ");

                        sb.Append("FontStyle=\"");
                        sb.Append(run.FontStyle.ToString());
                        sb.Append("\" ");

                        sb.Append("FontName=\"");
                        sb.Append(run.FontFamily.Source);
                        sb.Append("\" ");

                        if (run.TextDecorations != null && run.TextDecorations.Count > 0)
                        {
                            bool isStrikeLine = false;
                            bool isUnderLine = false;
                            foreach (TextDecoration td in run.TextDecorations)
                            {
                                if (td.Location == TextDecorationLocation.Underline)
                                {
                                    isUnderLine = true;
                                }
                                else if (td.Location == TextDecorationLocation.Strikethrough)
                                {
                                    isStrikeLine = true;
                                }
                            }

                            if (isStrikeLine)
                            {
                                sb.Append("StrikeLine=\"True\" ");
                            }

                            if (isUnderLine)
                            {
                                sb.Append("UnderLine=\"True\" ");
                            }
                        }

                        sb.Append("BaseLineAlignment=\"");
                        sb.Append(run.BaselineAlignment.ToString());
                        sb.Append("\" ");

                        sb.Append(">");
                        sb.Append(ReplaceXmlChars(run.Text));
                        sb.Append("</Text>");
                    }

                }

                sb.Append("<Text />");//每段结尾添加<Text />表示换行。
            }

            string s = sb.ToString();
            if (s.EndsWith("<Text />"))
            {
                s = s.Substring(0, s.Length - 8);
            }

            XmlNode commentSetNode = title.XmlData.SelectSingleNode("CommentSet");
            if (commentSetNode == null)
            {
                commentSetNode = title.XmlData.AppendXml("<CommentSet />");
            }

            if (commentSetNode == null)
            {
                MessageBox.Show("发生意外，没有找到标题的CommentSet节点，且无法添加。编辑标题备注文本失败。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            Action actXmlDataInnerXml = new Action(title.ID, -1, title.GetType().Name,
                "XmlCommentInnerXml", commentSetNode.InnerXml, s);

            //注意此处的顺序。不能在Action之前清除。
            commentSetNode.InnerXml = "";//先清除所有子节点。

            commentSetNode.InnerXml = s;

            mi.Add(actXmlDataInnerXml);

            title.BuildTitle();

            return true;
        }

        /// <summary>
        /// 将文本中的小于号和&符转换成&lt;和&amp;以防止造成Xml格式失效。
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        internal static string ReplaceXmlChars(string source)
        {
            if (source == null) return null;
            if (source.Length <= 0) return string.Empty;

            //Xml预定的转义字符有五个，只有“<”和“&”是严格禁止使用的。
            string result = source.Replace("&", "&amp;");
            result = result.Replace("<", "&lt;");
            result = result.Replace(">", "&gt;");
            result = result.Replace("'", "&apos;");
            result = result.Replace("\"", "&quot;");
            return result;
        }

        /// <summary>
        /// 将Xml文本中的&lt;和&amp;转换回小于号和&符。
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        internal static string RestoreXmlChars(string source)
        {
            if (source == null) return null;
            if (source.Length <= 0) return string.Empty;

            //Xml预定的转义字符有五个，只有“<”和“&”是严格禁止使用的。
            string result = source.Replace("&quot;", "\"");
            result = result.Replace("&apos;", "'");
            result = result.Replace("&gt;", ">");
            result = result.Replace("&lt;", "<");
            result = result.Replace("&amp;", "&");
            return result;
        }

        private List<Title> masterTitles;

        public List<Title> MasterRichTexts
        {
            get { return masterTitles; }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            mainRTB.Selection.Text = (sender as Button).Content.ToString();
        }

        private void btnOk_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;

            WriteLinesToAllTitleXmlData();

            this.Close();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;

            this.Close();
        }

        private void btnCut_Click(object sender, RoutedEventArgs e)
        {
            mainRTB.Cut();
        }

        private void btnCopy_Click(object sender, RoutedEventArgs e)
        {
            mainRTB.Copy();
        }

        private void btnPaste_Click(object sender, RoutedEventArgs e)
        {
            mainRTB.Paste();
        }

        private void btnBold_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                bool appendASpace = false;
                if (mainRTB.Selection.Text.Length == 0)
                {
                    appendASpace = true;
                    mainRTB.Selection.Text = " ";//加个空格，这样就便于保留格式了。
                }

                FontWeight fw = (FontWeight)mainRTB.Selection.GetPropertyValue(TextElement.FontWeightProperty);

                if (fw == FontWeights.Bold)
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
                }
                else
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                }

                if (appendASpace)
                {
                    this.mainRTB.Selection.Select(this.mainRTB.Selection.End, this.mainRTB.Selection.End);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnItalic_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                bool appendASpace = false;
                if (mainRTB.Selection.Text.Length == 0)
                {
                    appendASpace = true;
                    mainRTB.Selection.Text = " ";//加个空格，这样就便于保留格式了。
                }

                FontStyle fs = (FontStyle)mainRTB.Selection.GetPropertyValue(TextElement.FontStyleProperty);

                if (fs == FontStyles.Italic)
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Normal);
                }
                else
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic);
                }

                if (appendASpace)
                {
                    this.mainRTB.Selection.Select(this.mainRTB.Selection.End, this.mainRTB.Selection.End);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnUnderLine_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                bool appendASpace = false;
                if (mainRTB.Selection.Text.Length == 0)
                {
                    appendASpace = true;
                    mainRTB.Selection.Text = " ";//加个空格，这样就便于保留格式了。
                }

                TextDecorationCollection tc = mainRTB.Selection.GetPropertyValue(Inline.TextDecorationsProperty) as TextDecorationCollection;

                bool isUnderline = false;

                var obj = mainRTB.Selection.GetPropertyValue(Inline.TextDecorationsProperty);

                TextDecorationCollection tdCollection = obj as TextDecorationCollection;

                if (tdCollection != null || tdCollection.Count > 0)
                {
                    foreach (TextDecoration td in tdCollection)
                    {
                        if (td.Location == TextDecorationLocation.Underline)
                        {
                            isUnderline = true;
                            break;
                        }
                    }
                }

                TextDecorationCollection newTC = new TextDecorationCollection();

                if (isUnderline)
                {
                    for (int i = tdCollection.Count - 1; i >= 0; i--)
                    {
                        TextDecoration td = tdCollection[i];
                        if (td.Location == TextDecorationLocation.Underline)
                        {
                            continue;
                        }

                        //TextDecoration newTD = new TextDecoration() { Location = td.Location };
                        //newTC.Add(newTD);
                        newTC.Add(Globals.UnderLineTextDecoration);
                    }
                }
                else
                {
                    for (int i = tdCollection.Count - 1; i >= 0; i--)
                    {
                        TextDecoration td = tdCollection[i];
                        //TextDecoration newTD = new TextDecoration() { Location = td.Location };
                        //newTC.Add(newTD);
                        newTC.Add(Globals.UnderLineTextDecoration);
                    }

                    //newTC.Add(new TextDecoration() { Location = TextDecorationLocation.Underline });
                    newTC.Add(Globals.UnderLineTextDecoration);
                }

                mainRTB.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, newTC);

                if (appendASpace)
                {
                    this.mainRTB.Selection.Select(this.mainRTB.Selection.End, this.mainRTB.Selection.End);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnStrikeLine_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                bool appendASpace = false;
                if (mainRTB.Selection.Text.Length == 0)
                {
                    appendASpace = true;
                    mainRTB.Selection.Text = " ";//加个空格，这样就便于保留格式了。
                }

                TextDecorationCollection tc = mainRTB.Selection.GetPropertyValue(Inline.TextDecorationsProperty) as TextDecorationCollection;

                bool isStrikeline = false;

                var obj = mainRTB.Selection.GetPropertyValue(Inline.TextDecorationsProperty);

                TextDecorationCollection tdCollection = obj as TextDecorationCollection;

                if (tdCollection != null || tdCollection.Count > 0)
                {
                    foreach (TextDecoration td in tdCollection)
                    {
                        if (td.Location == TextDecorationLocation.Strikethrough)
                        {
                            isStrikeline = true;
                            break;
                        }
                    }
                }

                TextDecorationCollection newTC = new TextDecorationCollection();

                if (isStrikeline)
                {
                    for (int i = tdCollection.Count - 1; i >= 0; i--)
                    {
                        TextDecoration td = tdCollection[i];
                        if (td.Location == TextDecorationLocation.Strikethrough)
                        {
                            continue;
                        }

                        TextDecoration newTD = new TextDecoration() { Location = td.Location };
                        newTC.Add(newTD);
                    }
                }
                else
                {
                    for (int i = tdCollection.Count - 1; i >= 0; i--)
                    {
                        TextDecoration td = tdCollection[i];
                        TextDecoration newTD = new TextDecoration() { Location = td.Location };
                        newTC.Add(newTD);
                    }

                    newTC.Add(new TextDecoration() { Location = TextDecorationLocation.Strikethrough });
                }

                mainRTB.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, newTC);

                if (appendASpace)
                {
                    this.mainRTB.Selection.Select(this.mainRTB.Selection.End, this.mainRTB.Selection.End);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        private Popup colorPickerPopup = new Popup() { IsOpen = false };

        private readonly ColorPicker colorPicker = new ColorPicker();

        private void colorPicker_Closed(object sender, EventArgs e)
        {
            colorPickerPopup.IsOpen = false;
        }

        private void colorPicker_ColorPicked(object sender, ColorPickedEventArgs e)
        {
            colorPickerPopup.IsOpen = false;

            SetTextColor((sender as ColorPicker).DestAction, e.PickedColor);
        }

        private void SetTextColor(ColorPicker.Destination dest, Brush newBrush)
        {
            switch (dest)
            {
                case ColorPicker.Destination.Foreground:
                    {
                        TextRange range = new TextRange(mainRTB.Selection.Start, mainRTB.Selection.End);
                        range.ApplyPropertyValue(FlowDocument.ForegroundProperty, newBrush);
                        break;
                    }
                case ColorPicker.Destination.Background:
                    {
                        TextRange range = new TextRange(mainRTB.Selection.Start, mainRTB.Selection.End);
                        range.ApplyPropertyValue(FlowDocument.BackgroundProperty, newBrush);
                        break;
                    }
            }
        }

        #region 用于定位拾色器的两个绑定

        private Binding textForegroundBinding = null;

        private Binding textBackgroundBinding = null;

        #endregion

        private void btnForeground_Click(object sender, RoutedEventArgs e)
        {
            if (colorPickerPopup.IsOpen)
            {
                colorPickerPopup.IsOpen = false;
            }

            if (textForegroundBinding == null)
            {
                textForegroundBinding = new Binding();
                textForegroundBinding.Source = btnForeground;
            }

            colorPickerPopup.SetBinding(Popup.PlacementTargetProperty, textForegroundBinding);

            ColorPicker colorpicker = colorPickerPopup.Child as ColorPicker;
            colorpicker.DestAction = ColorPicker.Destination.Foreground;
            colorPickerPopup.IsOpen = true;
        }

        private void btnBackground_Click(object sender, RoutedEventArgs e)
        {
            if (colorPickerPopup.IsOpen)
            {
                colorPickerPopup.IsOpen = false;
            }

            if (textBackgroundBinding == null)
            {
                textBackgroundBinding = new Binding();
                textBackgroundBinding.Source = btnBackground;
            }

            colorPickerPopup.SetBinding(Popup.PlacementTargetProperty, textBackgroundBinding);

            ColorPicker colorpicker = colorPickerPopup.Child as ColorPicker;
            colorpicker.DestAction = ColorPicker.Destination.Background;
            colorPickerPopup.IsOpen = true;
        }

        private void btnTopMark_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var currentAlignment = mainRTB.Selection.GetPropertyValue(Inline.BaselineAlignmentProperty);

                BaselineAlignment newAlignment;

                if (currentAlignment == DependencyProperty.UnsetValue)
                {
                    newAlignment = BaselineAlignment.Top;
                }
                else
                {
                    newAlignment =
                        ((BaselineAlignment)currentAlignment == BaselineAlignment.Top) ?
                            BaselineAlignment.Baseline : BaselineAlignment.Top;
                }

                mainRTB.Selection.ApplyPropertyValue(Inline.BaselineAlignmentProperty, newAlignment);

                if (newAlignment == BaselineAlignment.Baseline)
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, mainRTB.FontSize);
                }
                else
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, mainRTB.FontSize / 2);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnBottomMark_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var currentAlignment = mainRTB.Selection.GetPropertyValue(Inline.BaselineAlignmentProperty);

                BaselineAlignment newAlignment;

                if (currentAlignment == DependencyProperty.UnsetValue)
                {
                    newAlignment = BaselineAlignment.Bottom;
                }
                else
                {
                    newAlignment =
                    ((BaselineAlignment)currentAlignment == BaselineAlignment.Bottom) ?
                        BaselineAlignment.Baseline : BaselineAlignment.Bottom;
                }

                mainRTB.Selection.ApplyPropertyValue(Inline.BaselineAlignmentProperty, newAlignment);

                if (newAlignment == BaselineAlignment.Baseline)
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, mainRTB.FontSize);
                }
                else
                {
                    mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, mainRTB.FontSize / 2);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 选中文本时，读取字体名称。此地应避免循环设定字体。
        /// </summary>
        private bool dontChangeFont = false;

        private string initializeText;

        private void cbFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //组合框中只有字体名称
            if (dontChangeFont) return;

            FontFamily ff = new FontFamily(cbFont.SelectedItem as string);
            mainRTB.Selection.ApplyPropertyValue(TextElement.FontFamilyProperty, ff);
        }

        private void btnUndo_Click(object sender, RoutedEventArgs e)
        {
            if (mainRTB.CanUndo)
            {
                mainRTB.Undo();
            }
        }

        private void btnRedo_Click(object sender, RoutedEventArgs e)
        {
            if (mainRTB.CanRedo)
            {
                mainRTB.Redo();
            }
        }

        private void mainRTB_SelectionChanged(object sender, RoutedEventArgs e)
        {
            FontFamily ff = mainRTB.Selection.GetPropertyValue(TextElement.FontFamilyProperty) as FontFamily;
            if (ff == null) return;

            if (cbFont.Items.Contains(ff.Source))
            {
                dontChangeFont = true;
                cbFont.SelectedItem = ff.Source;
                dontChangeFont = false;
            }

            var ofs = mainRTB.Selection.GetPropertyValue(TextElement.FontStyleProperty);
            if (ofs is FontStyle)
            {
                FontStyle fs = (FontStyle)ofs;
                if (fs == FontStyles.Italic)
                {
                    btnItalic.IsChecked = true;
                }
                else btnItalic.IsChecked = false;
            }
            else btnItalic.IsChecked = false;

            var ofw = mainRTB.Selection.GetPropertyValue(TextElement.FontWeightProperty);
            if (ofw is FontWeight)
            {
                FontWeight fw = (FontWeight)ofw;
                if (fw == FontWeights.Bold)
                {
                    btnBold.IsChecked = true;
                }
                else btnBold.IsChecked = false;
            }
            else btnBold.IsChecked = false;

            TextDecorationCollection tc = mainRTB.Selection.GetPropertyValue(Inline.TextDecorationsProperty) as TextDecorationCollection;
            if (tc == null)
            {
                btnUnderLine.IsChecked = false;
                btnStrikeLine.IsChecked = false;
            }
            else
            {
                bool isUnderLine = false;
                bool isStrikeLine = false;
                foreach (TextDecoration td in tc)
                {
                    if (td.Location == TextDecorationLocation.Underline)
                    {
                        isUnderLine = true; break;
                    }
                }

                foreach (TextDecoration td in tc)
                {
                    if (td.Location == TextDecorationLocation.Strikethrough)
                    {
                        isStrikeLine = true;
                    }
                }

                btnUnderLine.IsChecked = isUnderLine;
                btnStrikeLine.IsChecked = isStrikeLine;
            }
        }

        private void mainRTB_KeyUp(object sender, KeyEventArgs e)
        {
            bool isShift = false, isCtrl = false;
            KeyboardDevice kd = e.KeyboardDevice;

            if ((kd.GetKeyStates(Key.LeftShift) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightShift) & KeyStates.Down) > 0)
            {
                isShift = true;
            }

            if ((kd.GetKeyStates(Key.LeftCtrl) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightCtrl) & KeyStates.Down) > 0)
            {
                isCtrl = true;
            }

            if (e.Key == Key.OemPlus)
            {
                if (isCtrl)
                {
                    if (isShift)
                    {
                        btnBottomMark_Click(null, null);
                        e.Handled = true;
                    }
                    else
                    {
                        btnTopMark_Click(null, null);
                        e.Handled = true;
                    }
                }
            }
            else if (e.Key == Key.T)
            {
                if (isCtrl && !isShift)
                {
                    btnStrikeLine_Click(null, null);
                    e.Handled = true;
                }
            }
        }

        private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            bool isShift = false, isCtrl = false;
            KeyboardDevice kd = e.KeyboardDevice;

            if ((kd.GetKeyStates(Key.LeftShift) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightShift) & KeyStates.Down) > 0)
            {
                isShift = true;
            }

            if ((kd.GetKeyStates(Key.LeftCtrl) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightCtrl) & KeyStates.Down) > 0)
            {
                isCtrl = true;
            }

            if (e.Key == Key.Enter)
            {
                if (isCtrl || isShift)
                {
                    //mainRTB.Selection.Text = "\r\n";
                    TextRange tr = new TextRange(mainRTB.Selection.Start, mainRTB.Selection.End);

                    var offcet = tr.Start.GetPositionAtOffset(0, LogicalDirection.Forward);

                    tr.Text = "\r\n";

                    mainRTB.CaretPosition = tr.End;

                    e.Handled = true;
                }
                else
                {
                    btnOk_Click(this, e);
                    e.Handled = true;
                }
            }
            if (e.Key == Key.E || e.Key == Key.L || e.Key == Key.R)
            {
                if (isCtrl)
                {
                    e.Handled = true; return;
                }
            }
        }

        private void cbFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cbFontSize.SelectedItem != null)
            {
                mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty,
                    double.Parse((cbFontSize.SelectedItem as ComboBoxItem).Content as string));
            }
        }

        private void mainRTB_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            bool isShift = false, isCtrl = false;
            KeyboardDevice kd = e.KeyboardDevice;

            if ((kd.GetKeyStates(Key.LeftShift) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightShift) & KeyStates.Down) > 0)
            {
                isShift = true;
            }

            if ((kd.GetKeyStates(Key.LeftCtrl) & KeyStates.Down) > 0 ||
                (kd.GetKeyStates(Key.RightCtrl) & KeyStates.Down) > 0)
            {
                isCtrl = true;
            }

            try
            {
                if (e.Key == Key.V && isCtrl && isShift == false)
                {
                    mainRTB.Selection.Text = Clipboard.GetText(TextDataFormat.UnicodeText);
                    TextRange sel = mainRTB.Selection;
                    sel.Select(sel.End, sel.End);
                    e.Handled = true;
                    return;
                }

                if (e.Key == Key.OemPeriod && isCtrl && isShift)
                {
                    object v = mainRTB.Selection.GetPropertyValue(TextElement.FontSizeProperty);

                    if (v == DependencyProperty.UnsetValue)
                    {
                        mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, 16.0);
                        return;
                    }
                    else
                    {
                        double oldFontSize = (double)v;
                        mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, oldFontSize + 2);
                        return;
                    }
                }

                if (e.Key == Key.OemComma && isCtrl && isShift)
                {
                    object v = mainRTB.Selection.GetPropertyValue(TextElement.FontSizeProperty);

                    if (v == DependencyProperty.UnsetValue)
                    {
                        mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, 16.0);
                        return;
                    }
                    else
                    {
                        double oldFontSize = (double)v;
                        mainRTB.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, oldFontSize - 2);
                        return;
                    }
                }

                if (e.Key == Key.U && isCtrl)
                {
                    btnUnderLine_Click(sender, e);
                    e.Handled = true;
                    return;
                }

                if (e.Key == Key.I)
                {
                    if (isCtrl && !isShift)
                    {
                        btnItalic_Click(null, null);
                        e.Handled = true;
                        return;
                    }
                }

                if (e.Key == Key.B)
                {
                    if (isCtrl && !isShift)
                    {
                        btnBold_Click(null, null);
                        e.Handled = true;
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(Globals.AppName,
                    "编辑器快捷键处理程序出现异常错误。异常信息如下：\r\n", ex.Message,
                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning,
                    null, MessageBoxResult.OK, Globals.MainWindow);
                return;
            }
        }

        private void btnTmp_Click(object sender, RoutedEventArgs e)
        {
            string str = XamlWriter.Save(mainRTB);
            MessageBox.Show(str);
        }
    }
}
